package org.surelink.radius.console;

import com.google.gson.Gson;
import org.apache.log4j.Logger;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Component;
import org.surelink.radius.console.message.Request;
import org.surelink.radius.console.message.RespBase;
import org.surelink.radius.console.message.Response;
import org.xsocket.connection.IConnectHandler;
import org.xsocket.connection.IDataHandler;
import org.xsocket.connection.INonBlockingConnection;

import java.io.IOException;
import java.nio.BufferUnderflowException;
import java.util.Map;

@Component
public class ConsoleHandler implements IDataHandler, IConnectHandler
{

    private static final Logger log = Logger.getLogger(ConsoleHandler.class);

    private Map<String, BaseProcess> hdlMap;

    @Autowired
    private Gson gson;

    @Autowired
    private LoginProcess loginProc;


    private final static String PREFIX = "\r\n$ surelink ~ ";


    public ConsoleHandler(Map<String, BaseProcess> hdlMap)
    {
        this.hdlMap = hdlMap;
    }

    public ConsoleHandler()
    {
    }

    @Override
    public boolean onConnect(INonBlockingConnection nbc) throws IOException, BufferUnderflowException
    {
        nbc.write(getUsage());
        nbc.write(PREFIX);
        return true;
    }

    public boolean onData(INonBlockingConnection nbc)
            throws IOException, BufferUnderflowException
    {

        String cmd = nbc.readStringByDelimiter("\r\n");


        if ("".equals(cmd.trim()) || PREFIX.equals(cmd.trim()))
        {
            nbc.write(PREFIX);
            return true;
        }


        log.info("接收管理命令：" + cmd);


        try
        {

            if (("quit").equals(cmd.trim()))
            {
                nbc.close();
                return true;
            }
            else if (("help").equals(cmd.trim()))
            {
                nbc.write(getUsage());
                nbc.write(PREFIX);
                return true;
            }
            else if (cmd.trim().startsWith("login"))
            {
                LoginControl lc = LoginControl.getLoginControl(nbc.getRemoteAddress().getHostAddress());
                if (lc.isOutOver())
                {
                    nbc.write(String.format("IP登录失败次数超过%s次，请一小时后再试\r\n", lc.getMax()));
                    nbc.close();
                    return true;
                }
                Response resp = loginProc.process(new Request(cmd));
                if (resp.getCode() == RespBase.SUCCESS.getCode())
                {
                    nbc.setAttachment(resp.getResult());
                    LoginControl.reset(nbc.getRemoteAddress().getHostAddress());
                    nbc.write("登录成功\r\n");
                }
                else
                {
                    lc.incr();
                    nbc.write("登录失败\r\n");
                }
                nbc.write(PREFIX);
                return true;

            }
            else
            {

                if (nbc.getAttachment() == null)
                {
                    nbc.write("请登录\r\n");
                    nbc.write(loginProc.process(new Request("login --help")).getMsg());
                    nbc.write(PREFIX);
                    return true;
                }

                String hkey = cmd.contains(" ") ? cmd.substring(0, cmd.indexOf(" ")) : cmd;
                BaseProcess process = hdlMap.get(hkey);
                Response resp = process.process(new Request(cmd));

                if (cmd.contains("--help"))
                    nbc.write(resp.getMsg());
                else
                    nbc.write(gson.toJson(resp));

                nbc.write(PREFIX);
            }
        }
        catch (Exception e)
        {
            nbc.write(e.getMessage() + "\r\n");
            nbc.write(PREFIX);
        }

        return true;
    }


    private String getUsage()
    {
        String usage = "支持的命令：\r\n";
        if (hdlMap.get("login") == null)
        {
            hdlMap.put("login", loginProc);
        }
        for (String cmdkey : hdlMap.keySet())
        {
            usage += String.format("%s 输入 %s --help 查看命令帮助\r\n", cmdkey, cmdkey);
        }
        return usage;
    }

}
